<?php
declare (strict_types = 1);

namespace app\common\server;

use Workerman\Lib\Timer;
use app\api\enum\User as UserEnum;
use app\api\model\User as UserModel;
use app\api\model\Communication as CommunicationModel;
use app\api\enum\Communication as CommunicationEnum;

class HandleMsg {

    // 心跳间隔时间
	protected static $heartbeat_time = 55;

    // 心跳检测
    public function heartCheck($worker) {
        Timer::add(10, function() use($worker) {
            $time_now = time();
            #这里统计下线人员的id
            $offline_user = [];
            
            foreach($worker->connections as $connection) {
                // 有可能该connection还没收到过消息，则lastMessageTime设置为当前时间
                if (empty($connection->lastMessageTime)) {
                    $connection->lastMessageTime = $time_now;
                    continue;
                }

                // 上次通讯时间间隔大于心跳间隔，则认为客户端已经下线，关闭连接
                if ($time_now - $connection->lastMessageTime > self::$heartbeat_time) {
                    #这里统计下线人员的id
                    $offline_user[] = $connection->uid;
                    #关闭连接
                    $connection->close();
                }
                
                #这里是一个用户下线后通知其他用户
                if (count($offline_user) > 0){
                    $msg = ['type'=>'offline','uid' => $connection->uid, "message"=>"用户【".implode(',',$offline_user)."】下线了"];
                    $connection->send(json_encode($msg));
                }
            }
        });
    }

    // 绑定用户id标识
    public function bindUid($connection, $worker, $message) {
        $connection->uid = $message['uid'];
        // 把用户id保存到连接池
        $worker->uidConnections[$connection->uid] = $connection;
    }

    // 发送文本或表情消息
    public function sendTextOrEmoji($worker, $message) {
        $text = nl2br(htmlspecialchars($message['data'])); 
        $fromid = $message['fromid'];
        $toid = $message['toid'];

        $messageArr = [
            'type' => 'text',
            'data' => $text,
            'fromid' => $fromid,
            'toid' => $toid,
            'time' => time(),
            'isread' => CommunicationEnum::uread
        ];

        // 判断连接池是否存在用户id
        if (isset($worker->uidConnections[$toid])){
            $conn = $worker->uidConnections[$toid];
            // 发送消息
            $conn->send(json_encode($messageArr));

            $this->saveMessage($messageArr);
        }
    }

    // 发送图片消息
    public function sendImage($worker, $message) {
        $toid = $message['toid'];
        $fromid =$message['fromid'];
        $img_name = $message['data'];
        $messageArr = [
            'type' => 'say_img',
            'fromid' => $fromid,
            'toid' => $toid,
            'img_name' => $img_name
        ];
        // 判断连接池是否存在用户id
        if (isset($worker->uidConnections[$toid])){
            $conn = $worker->uidConnections[$toid];

            // 发送消息
            $conn->send(json_encode($messageArr));

            $this->saveMessage($messageArr);
        }
    }

    // 发送在线状态
    public function sendOnlineStatus($worker, $message) {
        $toid = $message['toid'];
        // 判断连接池是否存在用户id
        if (isset($worker->uidConnections[$toid])){
            $conn = $worker->uidConnections[$toid];
            // 发送消息
            $conn->send(json_encode(['type' => "online", "status" => $this->isOnline($conn)]));
        }
    }

    // 判断用户是否在线
	public function isOnline($connection) {
		$time_now = time();
		// 上次通讯时间间隔大于心跳间隔，则认为客户端已经下线
		if($time_now - $connection->lastMessageTime > self::$heartbeat_time) {
			return false;
		} else {
			return true;
		}
	}

    // 保存发送的消息到数据库
    public function saveMessage($message){
        $datas = [
            'fromid' => $message['fromid'],
            'fromname' => UserModel::getIdName($message['fromid']),
            'toid' => $message['toid'],
            'toname' => UserModel::getIdName($message['toid']),
            'content' => $message['data'],
            'time' => time(),
            'isread' => CommunicationEnum::uread,
            'type' => UserEnum::type
        ];

        CommunicationModel::add($datas);
    }
}